
function load_firtree_material() {
        var fragmentShader = getShader(gl, "firtree-fs");
        var vertexShader = getShader(gl, "firtree-vs");

	var mat = new Object(); 

        s = gl.createProgram();
        gl.attachShader(s, vertexShader);
        gl.attachShader(s, fragmentShader);
        gl.linkProgram(s);

        if (!gl.getProgramParameter(s, gl.LINK_STATUS)) {
            alert("Could not initialise landscape shaders");
        }

        gl.useProgram(s);

	var attrib;
        mat.attribs = {};
	mat.attribs["pos"] = gl.getAttribLocation(s, "pos");
	mat.attribs["norm"] = gl.getAttribLocation(s, "norm");
	
        mat.uniforms = {}; 
	mat.uniforms["P"] = gl.getUniformLocation(s, "P");
        mat.uniforms["V"] = gl.getUniformLocation(s, "V");
        mat.uniforms["M"] = gl.getUniformLocation(s, "M");
        mat.uniforms["origin"] = gl.getUniformLocation(s, "origin");
        mat.uniforms["rot"] = gl.getUniformLocation(s, "rot");

	gl.useProgram(null);


	mat.s = s;

	return mat;
}

function create_firtree(number, minv, maxv, hf) {
	
	var stride = 6; // in floats

	var mesh = new Object();	

	
	mesh.vb = new Float32Array(firtree_vertex_buffer);
	mesh.vb_id = gl.createBuffer();
	mesh.vertex_stride = stride*Float32Array.BYTES_PER_ELEMENT;
	mesh.prim_type = gl.TRIANGLES;

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.vb_id);
        gl.bufferData(gl.ARRAY_BUFFER, mesh.vb, gl.STATIC_DRAW);
	gl.bindBuffer(gl.ARRAY_BUFFER, null);

	mesh.pos = new Array();
	mesh.rot = new Array();
	mesh.number = number;
	var t, x,y,z;
	var hf_pos = new vec2();
	for(var i=0; i <number; ++i) {
		t = Math.random();
		mesh.pos[3*i + 0] = x = minv.x * (1-t) + maxv.x*t;
		t = Math.random();
		mesh.pos[3*i + 2] = z = minv.z * (1-t) + maxv.z*t;
		t = Math.random();

		hf_pos.x = (x+0.5*hf.size)*hf.heightmap_scale;
		hf_pos.y = (z+0.5*hf.size)*hf.heightmap_scale;
		mesh.pos[3*i + 1] = hf.y_scale * fbm(hf_pos, 4, 2.0, 0.5); //minv.y * (1-t) + maxv.y*t;
		mesh.rot[i] = 2.0*Math.PI*Math.random();
	}

	return mesh;
}


function draw_firtree(m, mat, model, view, proj) {

	gl.useProgram(mat.s);
	gl.bindBuffer(gl.ARRAY_BUFFER, m.vb_id);	
	
	if(mat.attribs.pos!=-1) {	
        	gl.enableVertexAttribArray(mat.attribs.pos);
        	gl.vertexAttribPointer(mat.attribs.pos, 3, gl.FLOAT, false, m.vertex_stride, 0);
	}
	if(mat.attribs.norm!=-1) {	
        	gl.enableVertexAttribArray(mat.attribs.norm);
        	gl.vertexAttribPointer(mat.attribs.norm, 3, gl.FLOAT, false, m.vertex_stride, 4*3);
	}

	if(mat.uniforms.M)
       		gl.uniformMatrix4fv(mat.uniforms.M, false, model);
	if(mat.uniforms.V)
       		gl.uniformMatrix4fv(mat.uniforms.V, false, view);
	if(mat.uniforms.P)
       		gl.uniformMatrix4fv(mat.uniforms.P, false, proj);

	for(var i=0; i<m.number; ++i) {
		if(mat.uniforms.origin)
       			gl.uniform3f(mat.uniforms.origin, m.pos[3*i+0], m.pos[3*i+1], m.pos[3*i+2]);
		if(mat.uniforms.rot)
       			gl.uniform1f(mat.uniforms.rot, m.rot[i]);
	
		gl.drawArrays(m.prim_type, 0, m.vb.length / 6);
	}


	gl.useProgram(null);
	gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
